package org.one.afternoon.controller;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.one.afternoon.common.Result;
import org.one.afternoon.common.SimpleUtils;
import org.one.afternoon.domain.Client;
import org.one.afternoon.domain.Hospital;
import org.one.afternoon.forest.FrontendClient;
import org.one.afternoon.service.ClientService;
import org.one.afternoon.service.HospitalService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.print.DocFlavor;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@RestController
@RequestMapping(value = "/client")
@Slf4j
public class ClientController {
    @Autowired
    private ClientService clientService;

    @Autowired
    private HospitalService hospitalService;

    @Autowired
    private FrontendClient frontendClient;

    /**
     * 测试接口 不连数据库
     *
     * @return Pong
     */
    @CrossOrigin // 跨域访问
    @GetMapping("/ping")
    @ResponseBody
    public Result<String> ping() {
        return Result.success("Pong");
    }

    /**
     * 查找所有数据
     *
     * @return 所有数据的集合
     */
    @CrossOrigin // 跨域访问
    @GetMapping("/all")
    @ResponseBody
    public Result<List<HospitalAndClient>> findAll() {
        List<HospitalAndClient> hospitalAndClientList = new ArrayList<>();
        List<Client> clientlist = clientService.list(null);
        List<Hospital> hospitalList = hospitalService.list(null);
        for (int i = 0; i < hospitalList.size(); i++) {
            HospitalAndClient hospitalAndClient = new HospitalAndClient();
            //*将数据库中的id传给前端 因为排序后前端的id会被打乱 (前端默认按照后端给的数据集合顺序操作)
            hospitalAndClient.setIpAddress(clientlist.get(i).getIpAddress());
            hospitalAndClient.setName(hospitalList.get(i).getName());
            hospitalAndClient.setStatus(clientlist.get(i).getStatus());
            hospitalAndClient.setCustomersSign(clientlist.get(i).getCustomersSign());
            hospitalAndClient.setId(clientlist.get(i).getId());
            hospitalAndClient.setHospitalId(clientlist.get(i).getHospitalId());
            hospitalAndClientList.add(hospitalAndClient);
        }
        //将数据进行排序操作 先按照状态排序:失败在前成功在后 再按照签名正序排序
        Pattern compile = Pattern.compile("\"resMessage\":\"[0-9]+-[0-9]+-[0-9]+-[0-9]+-[0-9]+-([0-9]+)\"");
        hospitalAndClientList.sort((h1, h2) -> {
                    if (Objects.equals(h1.getStatus(), h2.getStatus())) {
                        int valueH1, valueH2;
                        Matcher matcherH1 = compile.matcher(h1.getCustomersSign());
                        Matcher matcherH2 = compile.matcher(h2.getCustomersSign());
                        if (matcherH1.find()) {
                            valueH1 = Integer.parseInt(matcherH1.group(1));
                        } else {
                            valueH1 = 0;
                        }
                        if (matcherH2.find()) {
                            valueH2 = Integer.parseInt(matcherH2.group(1));
                        } else {
                            valueH2 = 0;
                        }
                        return valueH1 - valueH2;
                    } else {
                        return h1.getStatus() - h2.getStatus();
                    }
                }
        );
        return Result.success(hospitalAndClientList);
    }

    /**
     * 查找一个或多个指定对象
     *
     * @param hospitalAndClient 模糊查询所需要的字段参数
     * @return HospitalAndClient集合
     */
    @CrossOrigin
    @PostMapping("/queryOne")
    @ResponseBody
    public Result<List<HospitalAndClient>> queryOne(@RequestBody HospitalAndClient hospitalAndClient) {

        //按照client名字进行模糊查询
        //创建hospitalAndClientListByName 用于返回数据
        List<HospitalAndClient> hospitalAndClientListByName = new ArrayList<>();
        //按照hospital状态和ip进行模糊查询
        //创建hospitalAndClientListByIpOrStatus 用于返回数据
        List<HospitalAndClient> hospitalAndClientListByIpOrStatus = new ArrayList<>();
        //创建Hospital查询构造器
        LambdaQueryWrapper<Hospital> lambdaQueryWrapperHospital = new LambdaQueryWrapper<>();
        //创建Client查询构造器
        LambdaQueryWrapper<Client> lambdaQueryWrapperClient = new LambdaQueryWrapper<>();
        //组装lambdaQueryWrapperHospital查询构造器 用like模糊查询
        lambdaQueryWrapperHospital.like(StringUtils.isNotBlank(hospitalAndClient.getName()), Hospital::getName, hospitalAndClient.getName());
        //组装lambdaQueryWrapperClient查询构造器 用like模糊查询
        lambdaQueryWrapperClient.like(StringUtils.isNotBlank(hospitalAndClient.getIpAddress()), Client::getIpAddress, hospitalAndClient.getIpAddress())
                .like(hospitalAndClient.getStatus() != null, Client::getStatus, hospitalAndClient.getStatus());
        //通过list方法查询数据 并获得集合
        List<Hospital> hospitalList = hospitalService.list(lambdaQueryWrapperHospital);
        //通过list方法查询数据 并获得集合
        List<Client> clientList = clientService.list(lambdaQueryWrapperClient);
        //遍历获取的hospital集合 并组装hospitalAndClientListByName
        for (Hospital hospital : hospitalList) {
            HospitalAndClient hacFromHospital = new HospitalAndClient();
            //组装需要返回的HospitalAndClient对象
            hacFromHospital.setName(hospital.getName());
            hacFromHospital.setId(hospital.getId());
            //获取对应的Client
            LambdaQueryWrapper<Client> lambdaQueryWrapperClients = new LambdaQueryWrapper<>();
            lambdaQueryWrapperClients.eq(hospital.getId() != null, Client::getHospitalId, hospital.getId());
            Client client = clientService.list(lambdaQueryWrapperClients).get(0);
            hacFromHospital.setStatus(client.getStatus());
            //若CustomersSign为空则插入"暂无数据"
            if (!SimpleUtils.IsNotBlank(client.getCustomersSign())) {
                hacFromHospital.setCustomersSign("暂无数据");
            } else {
                hacFromHospital.setCustomersSign(client.getCustomersSign());
            }
            hacFromHospital.setHospitalId(client.getHospitalId());
            hacFromHospital.setIpAddress(client.getIpAddress());
            //将组装完成的HospitalAndClient对象装入list中
            hospitalAndClientListByName.add(hacFromHospital);
        }
        //遍历获取的client集合 并组装hospitalAndClientListByIpOrStatus
        for (Client client : clientList) {
            HospitalAndClient hacFromClient = new HospitalAndClient();
            //组装需要返回的HospitalAndClient对象
            hacFromClient.setHospitalId(client.getHospitalId());
            hacFromClient.setIpAddress(client.getIpAddress());
            hacFromClient.setStatus(client.getStatus());
            //获取对应的Hospital
            LambdaQueryWrapper<Hospital> lambdaQueryWrapperHospitals = new LambdaQueryWrapper<>();
            lambdaQueryWrapperHospitals.eq(client.getHospitalId() != null, Hospital::getId, client.getHospitalId());
            Hospital hospital = hospitalService.list(lambdaQueryWrapperHospitals).get(0);
            hacFromClient.setId(client.getId());
            hacFromClient.setName(hospital.getName());
            //若CustomersSign为空则插入"暂无数据"
            if (!SimpleUtils.IsNotBlank(client.getCustomersSign())) {
                hacFromClient.setCustomersSign("暂无数据");
            } else {
                hacFromClient.setCustomersSign(client.getCustomersSign());
            }
            hospitalAndClientListByIpOrStatus.add(hacFromClient);
        }
        List<HospitalAndClient> hospitalAndClientList = new ArrayList<>(hospitalAndClientListByName);
        hospitalAndClientList.retainAll(hospitalAndClientListByIpOrStatus);
        return Result.success(hospitalAndClientList);
    }

    /**
     * 插入数据
     *
     * @param hospitalAndClient 要插入的对象
     * @return 添加失败/添加成功
     */
    @CrossOrigin
    @PostMapping("/insertOne")
    @ResponseBody
    public Result<String> addOne(@RequestBody HospitalAndClient hospitalAndClient) {

        //如果前端的传来的关键数值为空 则返回"数据缺失字段"
        if (!SimpleUtils.IsNotBlank(hospitalAndClient.getName(), hospitalAndClient.getIpAddress())) {
            return Result.error("数据缺失");
        }

        //将前端传来的数据拆分成Client/Hospital
        Client client = new Client();
        Hospital hospital = new Hospital();

        //判断前端传来的hospitalAndClient对象中是否有id 若没有则自动插入id;
        if (hospitalAndClient.getHospitalId() == null) {
            long count = clientService.count();
            count++;
            client.setHospitalId(count);
            client.setId(count);
            hospital.setId(count);
            hospital.setOrgCode(String.valueOf(count));
        }

        //组装Client 前置机状态默认为0/失败
        client.setIpAddress(hospitalAndClient.getIpAddress());
        client.setStatus(0);

        //组装Hospital 版本默认为1
        hospital.setVersion("1");
        hospital.setName(hospitalAndClient.getName());

        System.out.println(client);
        System.out.println(hospital);

        //判断前端传来的医院数据是否存在 若存在则返回"该数据已存在"字段
        LambdaQueryWrapper<Hospital> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(StringUtils.isNotBlank(hospital.getName()), Hospital::getName, hospital.getName());
        if (hospitalService.list(lambdaQueryWrapper).size() != 0) {
            System.out.println(hospitalService.list(lambdaQueryWrapper));
            return Result.error("该数据已存在");
        } else {
            boolean clientResult = clientService.save(client);
            boolean hospitalResult = hospitalService.save(hospital);
            if (clientResult && hospitalResult) {
                return Result.success("添加数据成功");
            }
        }
        return Result.error("添加数据失败");
    }

    /**
     * 删除指定对象
     *
     * @param index 删除对象的索引值
     * @return 删除成功/删除失败
     */
    @CrossOrigin
    @PostMapping("/deleteOne")
    @ResponseBody
    public Result<String> deleteOne(@RequestParam Integer index) {
        boolean hospitalResult = hospitalService.removeById(index);
        boolean clientResult = clientService.removeById(index);
        if (hospitalResult && clientResult) {
            return Result.success("删除成功");
        }
        return Result.error("删除失败");
    }

    /**
     * 修改指定对象
     *
     * @param client 修改对象
     * @return 修改成功/修改失败
     */
    @CrossOrigin
    @PostMapping("/updateOne")
    @ResponseBody
    public Result<String> updateOne(@RequestBody Client client) {
        LambdaUpdateWrapper<Client> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.set(StringUtils.isNotBlank(client.getIpAddress()), Client::getIpAddress, client.getIpAddress())
                .set(client.getStatus() != null, Client::getStatus, client.getStatus())
                .eq(client.getId() != null, Client::getId, client.getId())
        ;
        boolean result = clientService.update(null, lambdaUpdateWrapper);
        if (result) {
            return Result.success("修改成功");
        }
        return Result.error("修改失败");
    }

    /**
     * 前置机状态查询 访问外部接口
     *
     * @param index ip地址索引
     * @return 状态
     */
    @CrossOrigin
    @PostMapping("/isHealth")
    @ResponseBody
    public Result<Integer> IsHealth(@RequestParam Integer index) {
        LambdaUpdateWrapper<Client> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        LambdaQueryWrapper<Client> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Client::getId, index);
        String ipAddress = clientService.list(lambdaQueryWrapper).get(0).getIpAddress();
        String status;
        try {
            status = clientService.isHealth(ipAddress);
            if (status == null) {
                return Result.error("数据库中无对应数据");
            }
            if (!status.equals("OK")) {
                status = "0";
                lambdaUpdateWrapper.set(Client::getStatus, 0)
                        .eq(Client::getId, index);
                clientService.update(lambdaUpdateWrapper);
            } else {
                status = "1";
                lambdaUpdateWrapper.set(Client::getStatus, 1)
                        .eq(Client::getId, index);
                clientService.update(lambdaUpdateWrapper);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error(e.getMessage());
        }
        return Result.success(Integer.valueOf(status));
    }

    /**
     * 获取医院签名 访问外部接口
     *
     * @param index ip地址索引
     * @return 签名
     */
    @CrossOrigin
    @PostMapping("/getCustomersSign")
    @ResponseBody
    public Result<String> getCustomersSign(@RequestParam Integer index) {
        String customersSign;
        try {
            Client client = clientService.getById(index);
            if (client == null) {
                return Result.error("数据库中无对应数据");
            }
            customersSign = frontendClient.getCustomersSign(client.getIpAddress());
            LambdaUpdateWrapper<Client> lambdaUpdateWrapper=new LambdaUpdateWrapper<>();
            lambdaUpdateWrapper.set(StringUtils.isNotBlank(customersSign),Client::getCustomersSign,customersSign)
                            .eq(Client::getId,index);
            clientService.update(lambdaUpdateWrapper);
        } catch (Exception e) {
            return Result.error(e.getMessage());
        }
        return Result.success(customersSign);
    }

    /**
     * 获取审核信息 访问外部接口
     *
     * @param name   姓名
     * @param idCard 身份证
     * @param ip     医院ip地址
     * @return 客户审核信息
     */
    @CrossOrigin
    @PostMapping("/getCustomersInfo")
    @ResponseBody
    public Result<String> getCustomersInfo(@RequestParam String name, @RequestParam String idCard, @RequestParam String ip) {
        String body = String.format("<xml><real_name>%s</real_name><id_card>%s</id_card></xml>", name, idCard);
        String customersInfo;
        try {
            customersInfo = frontendClient.getCustomersInfo(ip, body);
        } catch (Exception e) {
            log.info(e.getMessage());
            return Result.error(e.getMessage());
        }
        return Result.success(customersInfo);
    }


    @CrossOrigin
    @PostMapping("/sync")
    @ResponseBody
    public Result<String> syncCustomersV2(@RequestParam String formatDate) {
        try{
            frontendClient.syncCustomersV2(formatDate);
            return Result.success("同步成功");
        }catch (Exception e){
            return Result.error("同步失败");
        }
    }

    @CrossOrigin
    @PostMapping("/insertAll")
    @ResponseBody
    public Result<String> addAll(@RequestParam String dialog) {
        //是否插入成功
        boolean flag = true;
        //数据是否均已存在
        boolean exist = true;
        //按照回车和空格分割文本
        String[] split = dialog.split("[\\s\\n]");
        //创建医院集合 用于存放医院名字
        List<String> hospitals = new ArrayList<>();
        //创建ip集合 用于存放ip
        List<String> ips = new ArrayList<>();
        //将文本拆成医院和ip并分别放入hospitals集合和ips集合
        for (int i = 0; i < split.length; i++) {
            if (i % 2 == 0) {
                hospitals.add(split[i]);
            } else {
                ips.add(split[i]);
            }
        }
        //创建client对象
        Client client = new Client();
        //创建hospital对象
        Hospital hospital = new Hospital();
        //统计目前有多少hospital
        long count = hospitalService.count();
        //往原来的基础上加一用于赋值
        count++;
        for (int i = 0; i < hospitals.size(); i++) {
            //组装Client
            client.setStatus(0);
            client.setId(count);
            client.setIpAddress(ips.get(i));
            client.setHospitalId(count);
            //组装Hospital
            hospital.setName(hospitals.get(i));
            hospital.setId(count);
            hospital.setVersion("1");
            hospital.setOrgCode(String.valueOf(count));
            LambdaQueryWrapper<Hospital> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(Hospital::getName, hospitals.get(i));
            //若医院重复 则不添加
            if (hospitalService.list(lambdaQueryWrapper).size() != 0) {
                continue;
            }
            //执行更新操作
            boolean hospitalSave = hospitalService.save(hospital);
            boolean clientSave = clientService.save(client);
            //若任意hospitalSave或clientSave插入失败则退出循环
            if (!(hospitalSave && clientSave)) {
                flag = false;
                break;
            }
            count++;
            exist = false;
        }
        if (exist) {
            return Result.error("数据均已存在");
        } else if (flag) {
            return Result.success("添加数据成功");
        }
        return Result.success("添加数据失败");
    }

    /**
     * 内部类 HospitalAndClient
     */
    @Data
    private static class HospitalAndClient {
        private Long hospitalId;
        private Long id;
        private String name;
        private String ipAddress;
        private Integer status;
        private String customersSign;
    }

    /**
     * 内部类 Customer
     */
    @Data
    private static class Customer {
        private String idCard;
        private String name;
    }
}
